package com.cuhk.gulimall.ware.service.impl;

import com.cuhk.common.constant.WareConstant;
import com.cuhk.gulimall.ware.entity.PurchaseDetailEntity;
import com.cuhk.gulimall.ware.feign.ProductFeignService;
import com.cuhk.gulimall.ware.service.PurchaseDetailService;
import com.cuhk.gulimall.ware.service.WareSkuService;
import com.cuhk.gulimall.ware.vo.MergeVo;
import com.cuhk.gulimall.ware.vo.PurchaseFinishVo;
import com.cuhk.gulimall.ware.vo.PurchaseItemFinishVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cuhk.common.utils.PageUtils;
import com.cuhk.common.utils.Query;

import com.cuhk.gulimall.ware.dao.PurchaseDao;
import com.cuhk.gulimall.ware.entity.PurchaseEntity;
import com.cuhk.gulimall.ware.service.PurchaseService;
import org.springframework.transaction.annotation.Transactional;

import static com.cuhk.common.constant.ControllerConstant.ExecuteOutcomeCode.FAILED_DEAL;
import static com.cuhk.common.constant.ControllerConstant.ExecuteOutcomeCode.SUCCESS_DEAL;
import static com.cuhk.common.constant.WareConstant.PurchaseDetailStatusEnum.BUYING;
import static com.cuhk.common.constant.WareConstant.PurchaseDetailStatusEnum.FAILED;
import static com.cuhk.common.constant.WareConstant.PurchaseStatusEnum.*;


@Service("purchaseService")
public class PurchaseServiceImpl extends ServiceImpl<PurchaseDao, PurchaseEntity> implements PurchaseService {

    @Autowired
    private PurchaseDetailService purchaseDetailService;

    @Autowired
    private WareSkuService wareSkuService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPageUnReceived(Map<String, Object> params) {
        QueryWrapper<PurchaseEntity> wrapper = new QueryWrapper<>();
        // 采购单的status应该是"新建"或者"未分配"
        // 分别对应着status：0/1
        wrapper.eq("status", 0).or().eq("status", 1);
        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                wrapper
        );
        return new PageUtils(page);
    }

    @Transactional
    @Override
    public Map<String, Object> mergePurchase(MergeVo mergeVo) {
        Long purchaseId;
        // 存储服务层返回结果
        Map<String, Object> result = new HashMap<>();

        // 如果采购单号不是空的
        // 则合并到已经存在的采购单中
        if(mergeVo.getPurchaseId() == null){
            PurchaseEntity purchaseEntity = new PurchaseEntity();
            purchaseEntity.setCreateTime(new Date());
            purchaseEntity.setUpdateTime(new Date());
            // 状态为新建
            purchaseEntity.setStatus(CREATED.getCode());
            this.save(purchaseEntity);
            purchaseId = purchaseEntity.getId();
        }
        else {
            PurchaseEntity purchaseEntity = this.getById(mergeVo.getPurchaseId());
            // 确认采购单的状态是0 || 1
            // 才能合并
            if(purchaseEntity.getStatus() != CREATED.getCode() && purchaseEntity.getStatus() != ASSIGNED.getCode()) {
                result.put("code", SUCCESS_DEAL);
                result.put("msg", "所选采购单不属于新建|已分配状态");
                return result;
            }
            purchaseEntity.setUpdateTime(new Date());
            purchaseEntity.setStatus(ASSIGNED.getCode());
            this.updateById(purchaseEntity);
            purchaseId = purchaseEntity.getId();
        }
        List<Long> items = mergeVo.getItems();
        List<PurchaseDetailEntity> targets = items.stream().map(detail -> {
            // PurchaseDetailEntity purchaseDetailEntity = purchaseDetailService.getById(detail);
            // purchaseDetailEntity.setPurchaseId(purchaseId);
            // return purchaseDetailEntity;
            PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();
            detailEntity.setId(detail);
            detailEntity.setPurchaseId(purchaseId);
            detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
            return detailEntity;
        }).collect(Collectors.toList());
        purchaseDetailService.updateBatchById(targets);
        result.put("code", SUCCESS_DEAL);
        result.put("msg", "合并采购商品至采购单成功");
        return result;
    }

    @Transactional
    @Override
    public void received(List<Long> ids) {
        // 确认当前采购单是"新建"或者"已分配"状态
        List<PurchaseEntity> entities = ids.stream().map(this::getById)
                .filter(item -> {
                    return item.getStatus() == CREATED.getCode() || item.getStatus() == ASSIGNED.getCode();
                })
                .collect(Collectors.toList());

        entities = entities.stream().peek(item -> {
            item.setStatus(RECEIVED.getCode());
            item.setUpdateTime(new Date());
        }).collect(Collectors.toList());
        this.updateBatchById(entities);

        // 修改采购单中各个采购目标的状态
        List<Long> detailIds = entities.stream().map(PurchaseEntity::getId).collect(Collectors.toList());
        List<PurchaseDetailEntity> detailEntites = purchaseDetailService.queryPurchaseDetailByBatch(detailIds);
        // 修改为正在采购状态
        detailEntites = detailEntites.stream().peek(item -> item.setStatus(BUYING.getCode())).collect(Collectors.toList());
        purchaseDetailService.updateBatchById(detailEntites);
    }

    @Transactional
    @Override
    public Map<String, Object> finishPurchase(PurchaseFinishVo purchaseFinishVo) {
        Map<String, Object> result = new HashMap<>();

        // 1. 改变采购项的状态
        boolean flag = true;
        List<PurchaseItemFinishVo> itemFinishVo = purchaseFinishVo.getItems();
        List<PurchaseDetailEntity> updateTarget = new ArrayList<>();
        for(PurchaseItemFinishVo vo : itemFinishVo) {
            PurchaseDetailEntity detailEntity = purchaseDetailService.getById(vo.getItemId());
            if(detailEntity != null) {
                // 采购不成功
                if(vo.getStatus() == FAILED.getCode()) {
                    flag = false;
                    detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FAILED.getCode());
                }
                // 采购成功
                else {
                    detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISHED.getCode());
                }
                detailEntity.setId(vo.getItemId());
                updateTarget.add(detailEntity);
            }
        }
        if(!flag) {
            result.put("code", FAILED_DEAL);
            result.put("msg", "采购单中部分商品没有采购完成");
            return result;
        }
        else {
            purchaseDetailService.updateBatchById(updateTarget);
        }

        // 2. 改变采购单的status
        Long purchaseId = purchaseFinishVo.getPurchaseId();
        PurchaseEntity purchaseEntity = this.getById(purchaseId);
        if(purchaseEntity == null) {
            result.put("code", FAILED_DEAL);
            result.put("msg", "采购单不存在");
            return result;
        }
        purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.FINISHED.getCode());
        purchaseEntity.setUpdateTime(new Date());
        this.updateById(purchaseEntity);

        // 3. 将采购到的商品进行入库
        for(PurchaseDetailEntity detailEntity : updateTarget) {
            wareSkuService.updateStock(detailEntity.getSkuId(), detailEntity.getWareId(), detailEntity.getSkuNum());
        }
        result.put("code", SUCCESS_DEAL);
        result.put("msg", "更新库存成功");
        return result;
    }

}